package com.dylan.历史.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.net.URLDecoder;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by ankang on 16/5/4.
 */
public class HttpUtils {
    private static Logger LOG = LoggerFactory.getLogger(HttpUtils.class);

    private static ObjectMapper jsonMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL).setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).disable(SerializationFeature.WRITE_NULL_MAP_VALUES);

    public static String sendHttpPost(String url, Map<String, Object> params) {
        // 创建HttpClientBuilder
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        // 创建HttpClient
        CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
        // 创建HttpPost
        HttpPost httpPost = new HttpPost(url);
        RequestConfig config = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(3000).build();
        httpPost.setConfig(config);
        // 创建参数队列
        List<NameValuePair> nvpList = new ArrayList<>(params.size());
        for (Map.Entry<String, Object> p : params.entrySet()) {
            if (p.getValue() != null) {
                nvpList.add(new BasicNameValuePair(p.getKey(), String.valueOf(p.getValue())));
            }
        }
        try {
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nvpList, "UTF-8");
            httpPost.setEntity(entity);
            LOG.info("发送请求，请求行:{}，请求参数:{}", httpPost.getRequestLine(), URLDecoder.decode(EntityUtils.toString(httpPost.getEntity(), "UTF-8"), "UTF-8"));
            CloseableHttpResponse response = closeableHttpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == 200) {
                String result = EntityUtils.toString(response.getEntity(), "UTF-8");
                LOG.info("请求成功，状态行:{}，请求结果:{}", response.getStatusLine().toString(), result);
                return result;
            }
            LOG.info("请求失败，状态行:{}", response.getStatusLine().toString());
        } catch (Exception e) {
            LOG.error("请求失败:", e);
        }
        return null;
    }

    public static String sendHttpGet(String url) {
        // 创建HttpClientBuilder
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        // 创建HttpClient
        CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
        // 创建HttpGet
        HttpGet httpGet = new HttpGet(url);
        RequestConfig config = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(3000).build();
        httpGet.setConfig(config);
        try {
            LOG.info("发送请求，请求行:{}", httpGet.getRequestLine());
            CloseableHttpResponse response = closeableHttpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == 200) {
                LOG.info("请求成功，状态行:{}", response.getStatusLine().toString());
                String result = EntityUtils.toString(response.getEntity(), "UTF-8");
                LOG.info("请求结果:{}", result);
                return result;
            }
            LOG.info("请求失败，状态行:{}", response.getStatusLine().toString());
        } catch (Exception e) {
            LOG.error("请求失败:", e);
        }
        return null;
    }

    public static String sendHttpPostByJson(String url, Map<String, Object> params) {
        try {
            return sendHttpPostByJson(url, jsonMapper.writeValueAsString(params));
        } catch (JsonProcessingException e) {
            LOG.error("数据格式化为JSON失败");
            return null;
        }
    }

    public static String sendHttpPostByJson(String url, String jsonParam) {
        return sendHttpPostByJson(url, jsonParam, "UTF-8");
    }

    private static String sendHttpPostByJson(String url, String jsonParam, String charset) {
        // 创建HttpClientBuilder
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        // 创建HttpClient
        CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
        // 创建HttpPost
        HttpPost httpPost = new HttpPost(url);
        RequestConfig config = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(3000).build();
        httpPost.setConfig(config);
        try {
            httpPost.setHeader("Content-Type", "application/json");
            StringEntity stringEntity = new StringEntity(jsonParam, charset);
            httpPost.setEntity(stringEntity);
            LOG.info("发送请求，请求行:{}", httpPost.getRequestLine());
            LOG.info("请求参数:{}", URLDecoder.decode(EntityUtils.toString(httpPost.getEntity(), "UTF-8"), "UTF-8"));
            CloseableHttpResponse response = closeableHttpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == 200) {
                LOG.info("请求成功，状态行:{}", response.getStatusLine().toString());
                String result = EntityUtils.toString(response.getEntity(), "UTF-8");
                LOG.info("请求结果:{}", result);
                return result;
            }
            LOG.info("请求失败，状态行:{}", response.getStatusLine().toString());
        } catch (Exception e) {
            LOG.error("请求失败:", e);
        }
        return null;
    }

    /**
     * 发送 SSL POST 请求（HTTPS），K-V形式
     * @param url API接口URL
     * @param params 参数map
     * @return
     */
    public static String sendSSLPost(String url, Map<String, Object> params) {
        // 创建HttpClient
        CloseableHttpClient closeableHttpClient = createSSLClientDefault();
        if (closeableHttpClient == null) {
            return null;
        }
        // 创建HttpPost
        HttpPost httpPost = new HttpPost(url);
        RequestConfig config = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(3000).build();
        httpPost.setConfig(config);
        // 创建参数队列
        List<NameValuePair> nvpList = new ArrayList<>(params.size());
        for (Map.Entry<String, Object> p : params.entrySet()) {
            if (p.getValue() != null) {
                nvpList.add(new BasicNameValuePair(p.getKey(), String.valueOf(p.getValue())));
            }
        }
        try {
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nvpList, "UTF-8");
            httpPost.setEntity(entity);
            LOG.info("发送请求，请求行:{}", httpPost.getRequestLine());
            LOG.info("请求参数:{}", URLDecoder.decode(EntityUtils.toString(httpPost.getEntity(), "UTF-8"), "UTF-8"));
            CloseableHttpResponse response = closeableHttpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == 200) {
                LOG.info("请求成功，状态行:{}", response.getStatusLine().toString());
                String result = EntityUtils.toString(response.getEntity(), "UTF-8");
                LOG.info("请求结果:{}", result);
                return result;
            }
            LOG.info("请求失败，状态行:{}", response.getStatusLine().toString());
        } catch (Exception e) {
            LOG.error("请求失败:", e);
        }
        return null;
    }

    private static CloseableHttpClient createSSLClientDefault(){
        try {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            X509TrustManager x509TrustManager = new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                }
                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                }
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };
            sslContext.init(null, new TrustManager[]{x509TrustManager}, null);
            return HttpClients.custom().setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext)).build();
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
        return null;
    }

}
